//////////////////////////////////////////////////////////////////////////
///	\file:	ViewContainer.h
///	Copyright (MingYou) 2009 - All Rights Reserved
///	Author:	Robert.Ma
///	Date:	[2009/08/05]
///	Description:
///
//////////////////////////////////////////////////////////////////////////
#pragma once
#include "InlineFunction.h"


template<class TView>
class ViewNode
{
public:
	ViewNode()
			: m_pPrevious(NULL),
			m_pView(NULL),
			m_pNext(NULL)
	{}

	virtual ~ViewNode()
	{
		::ClearPointer(m_pView);

		if ( NULL != m_pPrevious )
		{
			m_pPrevious->SetNext(NULL);

			::ClearPointer(m_pPrevious);
		}

		if ( NULL != m_pNext )
		{
			m_pNext->SetPrev(NULL);

			::ClearPointer(m_pNext);
		}
	}

	ViewNode* Previous()
	{
		return m_pPrevious;
	}

	ViewNode* Next()
	{
		return m_pNext;
	}

	TView* RealPointer()
	{
		return m_pView;
	}

	void SetPrev(ViewNode* pNode)
	{
		m_pPrevious = pNode;
	}

	void SetNext(ViewNode* pNode)
	{
		m_pNext = pNode;
	}

	void SetView(TView* pView)
	{
		m_pView = pView;
	}

private:
	ViewNode*	m_pPrevious;
	ViewNode*	m_pNext;
	TView*		m_pView;
};

template<class TView>
class ViewContainer
{
public:
	typedef enum emInOut
	{
		FILO,	//	First in first out.
		FIFO	//	First in last out.
	} EM_IN_OUT;

	ViewContainer()
			: m_pFirstNode(NULL),
			m_pLastNode(NULL),
			m_eStyle(FILO)
	{}

	virtual ~ViewContainer()
	{
		Release();
	}

	void SetStackStyle(EM_IN_OUT eStyle)
	{
		m_eStyle = eStyle;
	}

	void Release()
	{
		::ClearPointer(m_pFirstNode);
		::ErasePoiter(m_pLastNode);
	}

	virtual void Push(TView* pView)
	{
		if ( NULL != pView )
		{
			ViewNode<TView>* pTmpNode = new ViewNode<TView>;

			pTmpNode->SetView(pView);

			if ( NULL != m_pFirstNode )
			{
				m_pLastNode->SetNext(pTmpNode);
				pTmpNode->SetPrev(m_pLastNode);
			}
			else
			{
				m_pFirstNode = pTmpNode;
			}

			m_pLastNode = pTmpNode;
		}
	}

	virtual void Pop()
	{
		ViewNode<TView>* pTmpNode = NULL;

		if ( FILO == m_eStyle )
		{
			pTmpNode = m_pLastNode->Previous();

			if ( NULL != pTmpNode )
			{
				pTmpNode->SetNext(NULL);
			}

			m_pLastNode->SetPrev(NULL);

			::ClearPointer(m_pLastNode);

			m_pLastNode = pTmpNode;

			if ( NULL == m_pLastNode )
			{
				m_pFirstNode = NULL;
			}
		}
		else
		{
			pTmpNode = m_pFirstNode->Next();

			if ( NULL != pTmpNode )
			{
				pTmpNode->SetPrev(NULL);
			}

			m_pFirstNode->SetNext(NULL);

			::ClearPointer(m_pFirstNode);

			m_pFirstNode = pTmpNode;

			if ( NULL == m_pFirstNode )
			{
				m_pLastNode = NULL;
			}
		}
	}

	TView* GetActiveView()
	{
		ViewNode<TView>* pTmpNode = NULL;

		if ( FILO == m_eStyle )
		{
			pTmpNode = m_pLastNode;
		}
		else
		{
			pTmpNode = m_pFirstNode;
		}

		if ( NULL != pTmpNode )
		{
			return pTmpNode->RealPointer();
		}
		else
		{
			return NULL;
		}
	}

	BOOL IsEmpty() const
	{
		return (NULL != m_pFirstNode);
	}

	ViewNode<TView>*	m_pFirstNode;
	ViewNode<TView>*	m_pLastNode;

	EM_IN_OUT		m_eStyle;
};
